import java.io.*;

public class Scanner {

	static Tokens sym; // last-scanned symbol for easy access
	static String ident; // content of last-scanned identifier
        static String number;
	private static int nextChar; // contains the character (or -1==EOF)
	// which needs to be scanned next
	private static LineNumberReader in;
	public static FileOutputStream outFile;
	private static PrintStream fileData;

	public Scanner(String sourceFile) {
		try {
			Scanner.in = new LineNumberReader(new FileReader(sourceFile));
			Scanner.in.setLineNumber(1);
			nextChar = readOne();
			outFile = new FileOutputStream(sourceFile + ".out");
			fileData = new PrintStream(outFile);
		} catch (IOException e) {
			e.printStackTrace();
			System.err.println("init: Errors accessing source file "
					+ sourceFile);
			System.exit(-2);
		}
	}

	public static void main(String args[]) {
		Scanner scanner = new Scanner(new String(args[0]));
		Tokens token = null;

		do {
			token = getSym();
			debug("token " + token.lexeme);
			fileData.print(" " + token.lexeme + " ");
		} while (token.name().compareTo(Tokens.END_OF.name()) != 0
				&& token.name().compareTo(Tokens.ERROR.name()) != 0);
		try {
			outFile.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// Returns the current line number
	public static int getLineNumber() {
		return Scanner.in.getLineNumber();
	}

	private static int readOne() {
		int localChar = 0;
		try {
			localChar = Scanner.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
		debug("read: " + (char) localChar);
		return localChar;
	}

	// For debug output just uncomment the println line
	private static void debug(String str) {
		// System.err.println(str);
	}

	private static boolean equals(char c1, Tokens t1) {
		if (Character.toString(c1).compareTo(t1.lexeme) == 0) {
			return true;
		}
		return false;
	}

	private static boolean equalsEOF(int i1) {
		if (i1 == -1) {
			return true;
		}
		return false;
	}

	public static Tokens getSym() {

		String temp = new String();

		// WhiteSpace
		if (Character.isWhitespace((char) nextChar)) {
			do {
				nextChar = readOne();
			} while (Character.isWhitespace(nextChar));
		}

		// EOF
		if (equalsEOF(nextChar)) {
			return Tokens.END_OF;
		}

		// Letter
		if (Character.isLetter((char) nextChar)) {
			do {
				temp = temp.concat(Character.toString((char) nextChar));
				nextChar = readOne();
			} while (Character.isLetterOrDigit((char) nextChar));

			if (temp.equalsIgnoreCase(Tokens.ERROR.lexeme))
                        {
                                ident = temp;
				return Tokens.IDENT;
                        }
			else if (temp.equalsIgnoreCase(Tokens.NUMBER.lexeme))
                        {
                                ident = temp;
				return Tokens.IDENT;
                        }
			else {
				for (Tokens t : Tokens.values())
					if (t.lexeme.equalsIgnoreCase(temp))
						return t;
                                ident = temp;
				return Tokens.IDENT;
			}

		} else if (Character.isDigit((char) nextChar)) { // Digit
			do {
				temp = temp.concat(Character.toString((char) nextChar));
				nextChar = readOne();
			} while (Character.isDigit((char) nextChar));
                        number = temp;
			return Tokens.NUMBER;

		} else if (equals((char) nextChar, Tokens.ASSIGN_OP)) { // Starting =
			nextChar = readOne();
			if (equals((char) nextChar, Tokens.ASSIGN_OP)) {
				nextChar = readOne();
				return Tokens.EQUAL;
			}
			return Tokens.ASSIGN_OP;

		} else if (equals((char) nextChar, Tokens.LESS_THAN)) { // Starting <
			nextChar = readOne();
			if (equals((char) nextChar, Tokens.ASSIGN_OP)) {
				nextChar = readOne();
				return Tokens.LESS_THAN_EQ;
			}
			return Tokens.LESS_THAN;

		} else if (nextChar == '!') { // Starting !
			nextChar = readOne();
			if (equals((char) nextChar, Tokens.ASSIGN_OP)) {
				nextChar = readOne();
				return Tokens.NOT_EQ;
			}
			return Tokens.ERROR;

		} else if (equals((char) nextChar, Tokens.GRT_THAN)) { // Startung >
			nextChar = readOne();
			if (equals((char) nextChar, Tokens.ASSIGN_OP)) {
				nextChar = readOne();
				return Tokens.GRT_THAN_EQ;
			}
			return Tokens.GRT_THAN;

		} else {
			for (Tokens t : Tokens.values())
				if (t.lexeme.equalsIgnoreCase(Character
						.toString((char) nextChar))) {
					nextChar = readOne();
					return t;
				}
			nextChar = readOne();
			return Tokens.ERROR;
		}
	}
}
